package cate.game.event.pointrace;

import cate.game.GameBody;
import cate.game.framework.advanced.AdvancedTimerEvent;
import cate.game.pvp.pointrace.timer.PointRaceTimerTask.Settings;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.time.DateTool;
import lombok.Data;
import lombok.Getter;
import lombok.ToString;
import org.springframework.data.annotation.Transient;

import java.util.StringJoiner;

import static cate.game.event.pointrace.PointRaceTimerEvent.EventType.*;

@Data
public class PointRaceTimerEvent implements AdvancedTimerEvent {

    @Transient
    @JsonIgnore
    private GameBody gameBody;

    @FunctionalInterface
    public interface Creator {
        PointRaceTimerEvent createTimerEvent(Settings settings);
    }

    public enum EventType {
        OPEN(1), CLOSE(2), SWITCH(3),
        RANK_DAY_RWD(4), RANK_SEASON_RWD(15), DAY_SPAN(20);

        @Getter
        final int flag;

        EventType(int flag) {
            this.flag = flag;
        }
    }

    public interface Handler {
        default void onOpenEvent(OpenEvent openEvent) {
        }

        default void onRankDayRwdEvent(RankDayRwdEvent rankDayRwdEvent) {
        }

        default void onRankSeasonDayRwdEvent(RankSeasonRwdEvent rankSeasonRwdEvent) {

        }

        default void onDaySpanEvent(DaySpanEvent daySpanEvent) {
        }

        default void onClosedEvent(ClosedEvent closedEvent) {
        }

        default void onSwitchEvent(SwitchEvent switchEvent) {
        }
    }

    private int id;
    private long executedTime = System.currentTimeMillis();
    private int season;
    private EventType eventType = OPEN;
    private OpenEvent openEvent;
    private RankDayRwdEvent rankDayRwdEvent;
    private RankSeasonRwdEvent rankSeasonRwdEvent;
    private DaySpanEvent daySpanEvent;
    private ClosedEvent closedEvent;
    private SwitchEvent switchEvent;

    @Override
    public boolean isMatch(long currentTimeMs) {
        return getExecutedTime() <= currentTimeMs;
    }

    @Data
    public static class OpenEvent {
        private long openTime;
        private long closedTime;
        private int session;

        @Override
        public String toString() {
            return new StringJoiner(", ", OpenEvent.class.getSimpleName() + "[", "]")
                    .add("openTime=" + DateTool.instance().format(openTime))
                    .add("closedTime=" + DateTool.instance().format(closedTime))
                    .add("session=" + session)
                    .toString();
        }
    }

    @ToString
    @Data
    public static class RankDayRwdEvent {
        private int day;
    }

    @ToString
    @Data
    public static class RankSeasonRwdEvent {
        private int day;
    }

    @ToString
    @Data
    public static class DaySpanEvent {
        private int fromDay;
        private int toDay;
    }

    @ToString
    @Data
    public static class ClosedEvent {
        private long closedTime = System.currentTimeMillis();
    }

    @ToString
    @Data
    public static class SwitchEvent {
        private long switchTime = System.currentTimeMillis();
        private int fromSeason;
        private int toSeason;
    }

    @Override
    public String toString() {
        StringJoiner stringJoiner = new StringJoiner(", ", PointRaceTimerEvent.class.getSimpleName() + "[", "]")
                .add("id=" + id)
                .add("executedTime=" + DateTool.instance().format(executedTime))
                .add("eventType=" + eventType);
        if (eventType == OPEN) {
            stringJoiner.add("openEvent=" + openEvent);
        } else if (eventType == DAY_SPAN) {
            stringJoiner.add("daySpanEvent=" + daySpanEvent);
        } else if (eventType == RANK_DAY_RWD) {
            stringJoiner.add("rankDayRwdEvent=" + rankDayRwdEvent);
        } else if (eventType == RANK_SEASON_RWD) {
            stringJoiner.add("rankSeasonRwdEvent=" + rankSeasonRwdEvent);
        } else if (eventType == CLOSE) {
            stringJoiner.add("closedEvent=" + closedEvent);
        }
        return stringJoiner.toString();
    }
}
